<template>
	<div class="table-box"	v-loading="tableBoxLoading">
		<p v-if="nodes.length === 0">暂无节点，请先添加节点</p>
		<el-tabs v-else ref="tabs" tab-position="left" v-model="activeNodeName" class="demo-tabs" @tab-click="handleClick">
			<el-tab-pane v-for="node in nodes" :label="node.nodeName" :key="node.nodeName" :name="node.nodeName">
				<el-table
					ref="nodeDiskTable"
					:data="node.nodeDevices"
					:row-key="(row:any)=>row.deviceId"
					v-loading="state.nodeDiskTableloading"
					element-loading-text="数据加载中..."
					htight="380"
					max-height="380"
					border
					@selection-change="handleNodeDiskChange"
				>
					<el-table-column type="selection" width="55"  :reserve-selection="true"></el-table-column>
					<el-table-column prop="osdId" label="OSDID"></el-table-column>
					<el-table-column prop="deviceId" label="磁盘ID"></el-table-column>
					<el-table-column prop="deviceStatus" label="节点磁盘状态" min-width="100"></el-table-column>
					<el-table-column prop="deviceType" label="类型"></el-table-column>
					<el-table-column prop="deviceUsedSize" label="用量">
						<template #default="{row}">
							{{ formatUnits(row.deviceUsedSize) }}
						</template>
					</el-table-column>
					<el-table-column prop="deviceTotalSize" label="容量">
						<template #default="{row}">
							{{ row.deviceTotalSize}}
						</template>
					</el-table-column>
					<el-table-column prop="devicePath" label="盘符"></el-table-column>
				</el-table>
			</el-tab-pane>
		</el-tabs>
	</div>
	<div class="btn-box">
		<div>
			<el-button type="primary" @click="addNode">添加节点</el-button>
			<el-button type="danger" @click="removeNode" :disabled="!activeNodeName">移除节点</el-button>
		</div>
		<div>
			<el-button type="primary" @click="addDisk" :disabled="!activeNodeName">添加磁盘</el-button>
			<el-button type="danger" @click="removeDisk" :disabled="!activeNodeName || removeDiskSelection.length <= 0">移除磁盘</el-button>
		</div>
	</div>
	<!-- addNode -->
	<el-dialog title="请选择节点"  v-model="nodeSelectVisible" :destroy-on-close="true">
		<el-table
			:data="addNodeTable"
			border
			@selection-change="handleAddNodeTableChange"
			v-loading="selNode"
		>
			<el-table-column type="selection" :selectable="(row:any)=>!row.disabled"></el-table-column>
			<el-table-column label="名称" prop="nodeName"></el-table-column>
			<el-table-column label="ip地址" prop="nodeIp"></el-table-column>
			<el-table-column label="存储池占用磁盘数" prop="poolUsedDevice"></el-table-column>
			<el-table-column label="管理磁盘数" prop="nodeUsedDevice"></el-table-column>
		</el-table>
		<template #footer>
			<el-button @click="nodeSelectVisible=false">取消</el-button>
			<el-button type="primary" @click="handleAddNode">确定</el-button>
		</template>
	</el-dialog>
	<!-- addDisk -->
	<el-dialog title="添加磁盘" :destroy-on-close="true" v-model="DiskSelectVisible">
		<div class="add-disk-info">
			<div><label>节点名称：</label><span>{{activeNodeName}}</span></div>
			<div><label>管理磁盘数：</label><span>{{totalDevice}}</span></div>
			<div><label>已使用磁盘数：</label><span>{{usedDevice}}</span></div>
		</div>
		<el-table
			:data="addDiskTable"
			border
			@selection-change="handleAddDiskChange"
		>
			<el-table-column type="selection" :selectable="handleSelectable"></el-table-column>
			<el-table-column prop="deviceId" label="磁盘ID"></el-table-column>
			<el-table-column prop="osdId" label="osdId"></el-table-column>
			<el-table-column prop="deviceType" label="类型"></el-table-column>
			<el-table-column prop="deviceUsedSize" label="用量">
				<template #default="{row}">
					{{ formatUnits(row.deviceUsedSize) }}
				</template>
			</el-table-column>
			<el-table-column prop="deviceTotalSize" label="容量">
				<template #default="{row}">
					{{ row.deviceTotalSize}}
				</template>
			</el-table-column>
			<el-table-column prop="devicePath" label="盘符"></el-table-column>
			<el-table-column prop="usedPool" label="存储池"></el-table-column>
		</el-table>
		<template #footer>
			<el-button @click="DiskSelectVisible=false">取消</el-button>
			<el-button type="primary" @click="handleAddDisk" :disabled="addDiskSelection.length===0">确定</el-button>
		</template>
	</el-dialog>
</template>

<script lang="ts" setup>
import { reactive, toRefs, onMounted, ref, getCurrentInstance, nextTick, markRaw } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { QuestionFilled } from '@element-plus/icons-vue';
import { storagePoolState, DiskItem } from '../interface/index';
import { useStorageApi } from '/@/api/storage';
import { useNodeApi } from '/@/api/node';
import { NodeDataRow, NodeDiskData } from '/@/types/index';
import { formatUnits } from '/@/utils/other';

const props = defineProps<{
	poolRow:storagePoolState | null
}>();
const { poolRow } = toRefs(props);
const storageApi = useStorageApi();
let state = reactive({
	activeNodeName: '',
	nodes: <NodeDataRow[]>[],
	nodeDiskTableloading: false
});
let { nodes, activeNodeName } = toRefs(state);
const currentInstance:any = getCurrentInstance();
const tableBoxLoading = ref(false);
const selNode = ref(true);

onMounted(() => {
	getPoolDiskList(true);
});

const getPoolDiskList = (loading:boolean = false) => {
	tableBoxLoading.value = loading;
	state.nodeDiskTableloading = loading;
	storageApi.getPoolDiskList({ poolName: poolRow.value?.poolName }).then((res) => {
		nodes.value = res.data;
		if (activeNodeName.value) {
			let flag = nodes.value.some(item => item.nodeName === activeNodeName.value);
			!flag && (activeNodeName.value = nodes.value[0]?.nodeName);
		} else {
			activeNodeName.value = nodes.value[0]?.nodeName;
		}
	}).finally(() => {
		state.nodeDiskTableloading = false;
		tableBoxLoading.value = false;
	});
};

// ws refresh list
const { proxy } = <any>getCurrentInstance();
proxy.mittBus.on('refresh-list', () => {
	getPoolDiskList(true);
});

const handleClick = () => {
	getPoolDiskList();
};

const handleNodeDiskChange = (val:NodeDiskData[]) => {
	removeDiskSelection.value = val;
};

// add node
let addNodeTable = ref<NodeDataRow[]>([]);
let selectNodeRow = ref<NodeDataRow[] | null>([]);
let nodeSelectVisible = ref(false);
const addNode = () => {
	nodeSelectVisible.value = true;
	selNode.value = true;
	useNodeApi().nodeList({}).then((res:any) => {
		addNodeTable.value = res.data.records;
		selNode.value = false;
		addNodeTable.value.forEach(element => {
			nodes.value.forEach(param => {
				if (element.nodeName === param.nodeName)element.disabled = true;
			});
		});
	});
};
const handleAddNode = () => {
	if (selectNodeRow.value) {
		storageApi.addNode({
			poolName: poolRow.value?.poolName,
			nodeNames: selectNodeRow.value.map(item => item.nodeName)
		}).then((res:any) => {
			if (res.code === 0) {
				ElMessage.success('添加【存储池添加节点】任务成功');
				nodeSelectVisible.value = false;
			}
		});
	}
};
const handleAddNodeTableChange = (val:NodeDataRow[]) => {
	selectNodeRow.value = val;
};

// remove node
const removeNode = () => {
	ElMessageBox.confirm(
		`移除节点后 存储池${poolRow.value?.poolName} 将不再使用 节点${activeNodeName.value}上的数据`,
		`存储池${poolRow.value?.poolName} 将移除 节点${activeNodeName.value}`,
		{
			confirmButtonText: '确认',
			cancelButtonText: '取消',
			type: 'warning',
		}
	).then(() => {
		tableBoxLoading.value = true;
		storageApi.removeNode({
			poolName: poolRow.value?.poolName,
			nodeName: activeNodeName.value
		}).then((res:any) => {
			if (res.code === 0) {
				ElMessage.success('添加【存储池移除节点】任务成功');
				// turn to next tab
				const tabs = nodes.value;
				tabs.forEach((tab, index) => {
					if (tab.nodeName === activeNodeName.value) {
						const nextTab = tabs[index + 1] || tabs[index - 1];
						if (nextTab) {
							activeNodeName.value = nextTab.nodeName;
						}
					}
				});
			}
		}).finally(() => {
			tableBoxLoading.value = false;
		});
	});
};

// add disk
const addDiskTable = ref<DiskItem[]>([]);
const totalDevice = ref(0);
const usedDevice = ref(0);
const addDiskSelection = ref<NodeDiskData[]>([]);
const DiskSelectVisible = ref(false);
const addDisk = () => {
	DiskSelectVisible.value = true;
	storageApi.getUnusedDisk({
		poolName: poolRow.value?.poolName,
		nodeName: activeNodeName.value
	}).then((res:any) => {
		addDiskTable.value = res.data.nodeDevices;
		totalDevice.value = res.data.totalDevice;
		usedDevice.value = res.data.usedDevice;
	});
};
const handleAddDisk = () => {
	storageApi.addStoragePoolDisk({
		osd: {
			nodeName: activeNodeName.value,
			osdIds: addDiskSelection.value.map(item => item.osdId)
		},
		poolName: poolRow.value?.poolName
	}).then(() => {
		ElMessage.success('添加【存储池添加磁盘】任务成功');
		DiskSelectVisible.value = false;
	});
};
const handleAddDiskChange = (val:NodeDiskData[]) => {
	addDiskSelection.value = val;
};
const handleSelectable = (row:NodeDiskData) => {
	return !row.usedPool;
};

// remove disk
const removeDiskSelection = ref<NodeDiskData[]>([]);
const removeDisk = () => {
	ElMessageBox({
		title: '存储池将移除以下磁盘',
		message: `${removeDiskSelection.value.map(item => `<div>${item.deviceId}</div>`).join('')}`,
		dangerouslyUseHTMLString: true,
		confirmButtonText: '确定',
		showCancelButton: true,
		cancelButtonText: '取消',
		buttonSize: 'default'
	}).then(() => {
		storageApi.removeStoragePoolDisk({
			osd: {
				nodeName: activeNodeName.value,
				osdIds: removeDiskSelection.value.map(item => item.osdId)
			},
			poolName: poolRow.value?.poolName
		}).then(() => {
			ElMessage.success('添加【存储池移除磁盘】任务成功');
			// clear all table selection
			currentInstance?.refs.nodeDiskTable.forEach((item:any) => {
				item.clearSelection();
			});
		}).catch(err => {
			ElMessageBox.confirm(
				`${err.message}`,
				'警告',
				{
					customClass: 'custom-box',
					confirmButtonText: '确定',
					showCancelButton: false,
					type: 'warning',
					icon: markRaw(QuestionFilled),
					dangerouslyUseHTMLString: true,
				}
			);

			nextTick(() => {
				let el = document.querySelector('.custom-box .el-message-box__container i') as HTMLElement;
				if (el) {
					el.setAttribute('title', err.data);
					el.style.cursor = 'pointer';
				}
			});
		});
	});
};

</script>

<style lang="scss" scoped>
.btn-box{
    margin-top: 10px;
	display: flex;
	justify-content: space-between;
}
.table-box{
    border: 1px solid #f0f0f0;
    padding: 10px;
		min-height: 400px;
	p{
		text-align: center;
		height: 400px;
    line-height: 400px;
	}
}
.add-disk-info{
	display: flex;
	align-items: center;
	margin-bottom: 10px;
	div{
		margin-right: 30px;
		label{
			font-weight: 700;
		}
	}
}
</style>